﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using System.Xml;
using Avalonia.Exusiai.Editor.Models;
using Core.ECS;
using Core.Tools;
using DynamicData;
using DynamicData.Binding;
using Newtonsoft.Json.Linq;
using ReactiveUI;

namespace Avalonia.Exusiai.Editor.ViewModels;

public class SceneHierarchyViewModel : ReactiveObject
{
    public static SceneHierarchyViewModel Instance;
    public static ObservableCollection<BTree> SceneTree { get; set; }
    public static BTree? SelectedItem
    {
        get => _selectedItem;
        set
        {
            if (_selectedItem == value) return;
            _selectedItem = value;
            if (value != null)
            {
                ObjectInspectionViewModel.UpdateData(value.Name);
            }
            else
            {
                ObjectInspectionViewModel.HaveSelectedItem = false;
            }
        }
    }
    public static void UpdateSelectedItemName(string name)
    {
        if (_selectedItem == null) return;
        _selectedItem.Name = name;
    }
    private static BTree? _selectedItem;
    public ICommand DeleteCommand { get; set; }
    public ICommand CreateCommand { get; set; }

    private void RemoveNodeCommand(BTree selectedItem)
    {
        if (selectedItem != null)
        {
            RemoveNodeRecursively(SceneTree, selectedItem);
        }
    }

    private void RemoveNodeRecursively(ObservableCollection<BTree> root, BTree selectedItem)
    {
        if (root.Contains(selectedItem))
        {
            root.Remove(selectedItem);
            RemoveNodeInScene(Actor.GetActor(selectedItem.Name));
        }
        else
        {
            foreach (BTree item in root)
            {
                if (item.SubTrees != null)
                {
                    RemoveNodeRecursively(item.SubTrees, selectedItem);
                }
            }
        }
    }
    private void RemoveNodeInScene(Actor actor)
    {
        if(actor.Transform.Children.Count > 0)
        {
            foreach(var child in actor.Transform.Children)
            {
                RemoveNodeInScene(child.Actor);
            }
        }
        Scene.Instance.ActorsList.Remove(actor);
        Scene.Instance.Actors.Remove(actor.Id);
        Scene.Instance.ActorsByName.Remove(actor.Name);
        SerializeHelper.Serialize(Scene.Instance, GlobalData.Instance.SelectedFolder + "/scene.xml");
    }
    private void CreateNodeCommand(BTree selectedItem)
    {
        if(selectedItem != null)
        {
            Actor actor = Actor.CreateActorWithoutRendererStart(); 
            if (selectedItem.Name == "Scene")
            {
                actor.Transform.Parent = null;
            }
            else
            {
                actor.Transform.Parent = Actor.GetActor(selectedItem.Name).Transform;
            }
            SerializeHelper.Serialize(Scene.Instance, GlobalData.Instance.SelectedFolder + "/scene.xml");
            selectedItem.SubTrees.Add(new BTree(actor.Name, new ObservableCollection<BTree>()));
        }
    }

    public SceneHierarchyViewModel()
    {
        DeleteCommand = ReactiveCommand.Create<BTree>(RemoveNodeCommand);
        CreateCommand = ReactiveCommand.Create<BTree>(CreateNodeCommand);
        SceneTree = new ObservableCollection<BTree>();
        Instance = this;
    }
    private void NewScene(BTree selectedItem)  { }
    public static void UpdateSceneTree()
    {
        Core.ECS.Scene scene = GlobalData.Instance.Scene;
        if (scene == null) return;
        BTree root = new BTree("Scene", new ObservableCollection<BTree>());
        SceneTree.Clear();
        SceneTree.Add(root);
        foreach (var actor in scene.ActorsList)
        {
            if (actor.Transform.Parent == null)
            {
                if (actor.Transform.Children.Count > 0)
                {
                    BTree tree = new BTree(actor.Name, new ObservableCollection<BTree>());
                    DfsBTree(tree, actor);
                    root.SubTrees.Add(tree);
                }
                else
                {
                    root.SubTrees.Add(new BTree(actor.Name, new ObservableCollection<BTree>()));
                }
            }
        }
    }
    public static void DfsBTree(BTree bTree, Core.ECS.Actor actor)
    {
        foreach (var child in actor.Transform.Children)
        {
            if(child.Children.Count > 0)
            {
                BTree tree = new BTree(child.Actor.Name, new ObservableCollection<BTree>());
                DfsBTree(tree, child.Actor);
                bTree.SubTrees.Add(tree);
            }
            else
            {
                bTree.SubTrees.Add(new BTree(child.Actor.Name, new ObservableCollection<BTree>()));
            }
        }
    }
}